﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using xmlBookstore.classLibrary;

namespace xmlBookstore
{
    public partial class frmXMLbookstore : Form
    {
        protected DataRep dr;
        private DataTable dtInventory, dtBookSelection;
        private String dtFilterTitle = "Title LIKE '*'";
        private String dtFilterAuthor = " and Author LIKE '*'";
        private String dtFilterCategory = "";
        private double totalBookSelectionPrice = 0;

        public frmXMLbookstore()
        {
            InitializeComponent();
            dr = new DataRep();
            dataBindDgvInventory();
            dataBindCbFilterCategory();
            dataBind();
        }

        // wtf je ovo?
        private void addBooksToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmAddBook frm = new frmAddBook(ref dr);
            frm.ShowDialog();
        }

        #region ***private methods***

        // feedanje podataka u formu
        private void dataBindDgvInventory()
        {
            // dgvInventory
            dtInventory = new DataTable();
            dtInventory = ToDataTable<Book>(dr.getInventory.Books);
            dtInventory.DefaultView.Sort = "Title";
            dgvInventory.DataSource = null;
            dgvInventory.Rows.Clear();
            dgvInventory.DataSource = dtInventory;
            dgvInventory.Refresh();
        }
        private void dataBindCbFilterCategory()
        {
            // cbFilterCategory
            cbFilterCategory.DataSource = null;
            cbFilterCategory.Items.Clear();
            cbFilterCategory.DataSource = dr.getCategoryList.Categories;
            //cbFilterCategory.DisplayMember = "ToString";
            cbFilterCategory.Refresh();
            cbFilterCategory.SelectedIndex = -1;
        }
        private void dataBind()
        {


            // dgvBookSelection
            dtBookSelection = new DataTable();
            dtBookSelection.Columns.Add("id", typeof(int));
            dtBookSelection.Columns.Add("Title", typeof(String));
            dtBookSelection.Columns.Add("Price", typeof(double));
            dtBookSelection.Columns.Add("Amount", typeof(int));
            dgvBookSelection.DataSource = dtBookSelection;
            dgvBookSelection.Refresh();

            //tbTotal
            tbTotal.Text = totalBookSelectionPrice.ToString();


        }

        // actual funkcija za brisanje invoicea
        private void clearInvoice()
        {
            // iz nekog cudnog razloga samo foreach nije dovoljan jer ne obrise sve (obrise pola ili tako nes), zato ovo ponavljanje
            while (dgvBookSelection.Rows.Count != 0)
            {
                DataGridViewRowCollection rows = dgvBookSelection.Rows;
                foreach (DataGridViewRow row in rows) dgvBookSelection.Rows.Remove(row); // makni sve redove sa invoicea
            }
            // refreshovi relevantnih polja
            dgvBookSelection.Refresh();
            totalBookSelectionPrice = 0;
            tbTotal.Text = totalBookSelectionPrice.ToString();
        }



        // ovo sluzi za generaciju DataTable objekta iz liste knjiga koji se onda spaja kao source dgv-a
        private DataTable ToDataTable<T>(List<T> items)
        {
            var tb = new DataTable(typeof(T).Name);
            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var prop in props)
            {
                //    if (prop.PropertyType == typeof(Category)) tb.Columns.Add(prop.Name, typeof(String));
                /*   else */
                tb.Columns.Add(prop.Name, prop.PropertyType);
            }

            foreach (var item in items)
            {
                var values = new object[props.Length];
                for (var i = 0; i < props.Length; i++)
                {
                    /*     if (props[i].PropertyType == typeof(Category))
                         {
                             values[i] = props[i].GetValue(item, null).ToString();
                         }
                         else */
                    values[i] = props[i].GetValue(item, null);
                }
                tb.Rows.Add(values);
            }
            return tb;
        }

        #endregion

        #region ***form control events***
        // FILTRIRANJE PO NAZIVU KNJIGE
        private void txtFilterTitle_TextChanged(object sender, EventArgs e)
        {
            dtFilterTitle = String.Concat("Title LIKE '*", txtFilterTitle.Text, "*'");
            dtInventory.DefaultView.RowFilter = dtFilterTitle + dtFilterAuthor + dtFilterCategory;
            dgvInventory.Refresh();

        }

        // FILTRIRANJE PO AUTORU KNJIGE
        private void txtFilterAuthor_TextChanged(object sender, EventArgs e)
        {
            dtFilterAuthor = String.Concat(" and Author LIKE '*", txtFilterAuthor.Text, "*'");
            dtInventory.DefaultView.RowFilter = dtFilterTitle + dtFilterAuthor + dtFilterCategory;
            dgvInventory.Refresh();


        }

        // TODO: treba implmentirat filtriranje po kategorijama i tipovima, no da se to sredi
        // potrebno je prvo u te comboboxove napuniti actual kategorije i tipove
        private void cbFilterCategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            //dtFilterCategory= String.Concat("and Cat LIKE '*", cbFilterCategory.SelectedItem.ToString(), "*'");
            //dtInventory.DefaultView.RowFilter = dtFilterTitle + dtFilterAuthor + dtFilterCategory;
            //dgvInventory.Refresh();
        }


        // brisanje svih filtara
        private void btnClearSearch_Click(object sender, EventArgs e)
        {
            txtFilterAuthor.Text = "";
            txtFilterTitle.Text = "";
            cbFilterCategory.SelectedIndex = -1;
            dtInventory.DefaultView.RowFilter = "Title LIKE '*' and Author LIKE '*'";

        }

        // dodavanje selekcije na invoice
        private void btnAddToInvoice_Click(object sender, EventArgs e)
        {
            DataGridViewSelectedRowCollection rows = dgvInventory.SelectedRows;
            // za svaku knjigu selektiranu u inventoriju
            foreach (DataGridViewRow row in rows)
            {
                // pocuclaj njene podatke i pripremi ih za spremanje na invoice
                DataRow myRow = (row.DataBoundItem as DataRowView).Row;
                //  test         bookSelection.ImportRow(myRow);
                String title = myRow.Field<String>("Title");
                double price = myRow.Field<double>("Price");
                int id = myRow.Field<int>("id");
                var values = new object[4];
                values[0] = id;
                values[1] = title;
                values[2] = price;
                values[3] = 1;  // kolicina koja ce biti upisana na invoice - ovo ce bit iskoristeno ako je vec nema na invoiceu, a ako ima bit ce stavljena appropriate kolicina

                // slijedeci foreach te if nakon njega sluze za provjeru jel se knjiga koja se dodaje vec
                // nalazi na invoiceu; ako se nalazi, poveca se njena kolicina na invoiceu, a ako ne, jednostavno se doda kao novi zapis
                bool alreadyOnInvoice = false;
                int idBookSelection;
                DataGridViewRowCollection dgvBookSelectionRows = dgvBookSelection.Rows;
                // prodji kroz knjige vec na invoiceu...
                foreach (DataGridViewRow dgvBookSelectionRow in dgvBookSelectionRows)
                {
                    DataRow myDgvBookSelectionRow = (dgvBookSelectionRow.DataBoundItem as DataRowView).Row;
                    idBookSelection = myDgvBookSelectionRow.Field<int>("id");
                    // ... da nadjes knjigu koju se dodaje, ako je vec tamo
                    if (id == idBookSelection)
                    {
                        alreadyOnInvoice = true;
                        // pocuclaj kolicinu vec na invoiceu
                        int amountBookSelection = myDgvBookSelectionRow.Field<int>("Amount");
                        // makni trenutni zapis o njoj sa invoicea
                        dgvBookSelection.Rows.Remove(dgvBookSelectionRow);
                        // dovrsi i dodaj novi zapis o njoj na invoice
                        amountBookSelection++;
                        values[3] = amountBookSelection;
                        dtBookSelection.Rows.Add(values);
                        break;
                    }
                }
                if (alreadyOnInvoice == false) // ako te knjige vec nema na invoiceu
                    dtBookSelection.Rows.Add(values); // dodaj je u invoice
                // dodaj vrijednost selektirane knjige na brojac vrijednosti
                totalBookSelectionPrice += price;
            }
            // refreshovi relevantnih polja
            tbTotal.Text = totalBookSelectionPrice.ToString();
            dgvBookSelection.Refresh();
        }

        // micanje selekcije sa invoicea
        private void btnRemoveFromInvoice_Click(object sender, EventArgs e)
        {
            DataGridViewSelectedRowCollection rows = dgvBookSelection.SelectedRows;
            foreach (DataGridViewRow row in rows)
            {
                // makni vrijednost selektirane knjige sa brojaca vrijednosti
                DataRow myRow = (row.DataBoundItem as DataRowView).Row;
                double price = myRow.Field<double>("Price");
                double amount = myRow.Field<int>("Amount");
                // ako na invoiceu ima vise od 1 knjige koja se brise
                if (amount > 1)
                {
                    // pocuclaj vrijednosti knjige koja se mice
                    String title = myRow.Field<String>("Title");
                    int id = myRow.Field<int>("id");
                    amount--;
                    var values = new object[4];
                    values[0] = id;
                    values[1] = title;
                    values[2] = price;
                    values[3] = amount;

                    dgvBookSelection.Rows.Remove(row);  // makni trenutni zapis o toj knjizi sa invoicea
                    dtBookSelection.Rows.Add(values); // dodaj novi zapis o toj knjizi sa invoicea
                }
                // ako nema, jednostavno obrisi njen zapis sa invoicea
                else dgvBookSelection.Rows.Remove(row);

                totalBookSelectionPrice -= price;  // oduzmi cijenu maknute knjige sa brojaca vrijednosti
            }
            // refreshovi relevantnih polja
            dgvBookSelection.Refresh();
            tbTotal.Text = totalBookSelectionPrice.ToString();
        }

        // micanje svega sa invoicea
        private void btnClearInvoice_Click(object sender, EventArgs e)
        {
            clearInvoice();
        }

        // obrada puchase akcije
        private void btnPurchase_Click(object sender, EventArgs e)
        {
            // ovaj cijeli dio sluzi za testiranje jel neka stavka na invoiceu ima vecu kolicinu od kolicine na lageru
            DataGridViewRowCollection rows = dgvBookSelection.Rows;
            bool abortPurchase = false;
            // za svaku stavku na invoiceu
            foreach (DataGridViewRow row in rows)
            {
                // iscupaj podatke koji su potrebni za testiranje
                DataRow myRow = (row.DataBoundItem as DataRowView).Row;
                int id = myRow.Field<int>("id");
                int amount = myRow.Field<int>("Amount");
                DataGridViewRowCollection inventoryRows = dgvInventory.Rows;
                // za svaku stavku koja se nalazi na lageru
                foreach (DataGridViewRow inventoryRow in inventoryRows)
                {
                    // iscupaj podatke potrebne za testiranje
                    DataRow myInventoryRow = (inventoryRow.DataBoundItem as DataRowView).Row;
                    int idInventory = myInventoryRow.Field<int>("id");
                    int amountInventory = myInventoryRow.Field<int>("CountInStorage");
                    // testiraj jel je ima dovoljno na lageru
                    if (id == idInventory)
                    {
                        // ako nema
                        if (amount > amountInventory)
                        {
                            String message = "The amount of item id=" + id.ToString() + " specified on the invoice is not available. Please adjust your order.";
                            System.Windows.Forms.MessageBox.Show(message, "Unable to process purchase");
                            abortPurchase = true;
                            break;
                        }
                    }
                }
                if (abortPurchase == true) break;
            }
            // ako svih knjiga ima dovoljno na lageru, obradi narudzbu
            if (abortPurchase == false)
            {

                String message = "Your purchase has been processed successfuly!\n\nInvoice:\n\n";
                double totalPrice = 0;
                // za svaku stavku na invoiceu
                foreach (DataGridViewRow row in rows)
                {
                    // pocuclaj podatke potrebne za ispis racuna
                    DataRow myRow = (row.DataBoundItem as DataRowView).Row;
                    int id = myRow.Field<int>("id");
                    int amount = myRow.Field<int>("Amount");
                    String title = myRow.Field<String>("Title");
                    double price = myRow.Field<double>("Price");
                    double itemPrice = price * (double)amount;
                    totalPrice += itemPrice;
                    String item = title + ", x" + amount.ToString() + ", " + itemPrice.ToString() + "kn\n";
                    message = message + item;

                    // maknimo odgovarajuću količinu upravo obrađene knjige sa lagera
                    // prodji kroz sve stavke na lageru da nadjes onu ciju kolicinu treba azurirati
                    DataGridViewRowCollection inventoryRows = dgvInventory.Rows;
                    foreach (DataGridViewRow inventoryRow in inventoryRows)
                    {
                        DataRow myInventoryRow = (inventoryRow.DataBoundItem as DataRowView).Row;
                        int idInventory = myInventoryRow.Field<int>("id");
                        // kada ju nadjes
                        if (id == idInventory)
                        {
                            // pocuclaj potrebne podatke
                            String titleInventory = myInventoryRow.Field<String>("Title");
                            String authorInventory = myInventoryRow.Field<String>("Author");
                            Category categoryInventory = myInventoryRow.Field<Category>("Cat");
                            double priceInventory = myInventoryRow.Field<double>("Price");
                            int amountInventory = myInventoryRow.Field<int>("CountInStorage");
                            amountInventory -= amount; // azuriraj kolicinu
                            int yearInventory = myInventoryRow.Field<int>("Year");
                            var values = new object[7];
                            values[0] = amountInventory;
                            values[1] = priceInventory;
                            values[2] = categoryInventory;
                            values[3] = yearInventory;
                            values[4] = authorInventory;
                            values[5] = titleInventory;
                            values[6] = idInventory;

                            dgvInventory.Rows.Remove(inventoryRow);  // obrisi stari zapis
                            dtInventory.Rows.Add(values);  // dodaj novi zapis sa azuriranom kolicinom

                            // azuriranje dr objekta - on je jos uvjek "master" datarepository ali dgvInventory
                            // odnosno dtInventory su nastali kao kopija njega (a ne referenca) stoga kako se 
                            // mijenjaju vrijednosti u njima moraju se mijenjat i u dr-u
                            foreach (Book book in dr.getInventory.Books)
                            {
                                if (idInventory == book.Id) book.CountInStorage -= amount;
                            }

                            ////////////////  // TODO: OVDJE RECIMO TREBA UKLJUCITI NAREDBE ZA IZMJENU PODATAKA O STANJU NA LAGERU U BAZI
                            ////////// JER OVO DO SADA JE SAMO AZURIRALO PODATKE U MEMORIJI

                        }
                    }
                }
                message = message + "\nTotal value: " + totalPrice.ToString() + "kn\n\nThank you for your purchase!";
                System.Windows.Forms.MessageBox.Show(message, "Success!");
                clearInvoice();
                dgvInventory.Refresh();

            }
        }

        // brisanje zapisa o knjizi sa inventara
        private void btnDelete_Click(object sender, EventArgs e)
        {
            DataGridViewSelectedRowCollection rows = dgvInventory.SelectedRows;
            // za svaku knjigu selektiranu u inventoriju
            foreach (DataGridViewRow row in rows)
            {
                // pocuclaj podatke potrebne za brisanje iz baze
                DataRow myRow = (row.DataBoundItem as DataRowView).Row;
                int id = myRow.Field<int>("id");
                // obrisi knjigu iz dgv-a
                dgvInventory.Rows.Remove(row);
                // obrisi knjigu iz datarepositorija
                Book bookToDelete = new Book();
                foreach (Book book in dr.getInventory.Books) if (id == book.Id)
                    {
                        bookToDelete = book;
                        break;
                    }
                dr.getInventory.Books.Remove(bookToDelete);
                dr.makeCategoryList();
                dataBindCbFilterCategory();

                // takodjer osvjeziti dr i listu kategorija i sve vezano uz njih

                ////////// TODO: S OBZIROM DA SADA IMAMO ID KNJIGE KOJU BRISEMO, OVDJE TREBA POZVATI FUNKCIJU KOJA CE JU
                ///////// OBRISATI I IZ BAZE (JER JE OVO DO SADA OBRISALO SAMO IZ MEMORIJE)



            }


        }

        // dodavanje nove knjige
        private void btnAddBook_Click(object sender, EventArgs e)
        {
            frmAddBook addBook = new frmAddBook(ref dr);
            addBook.ShowDialog();
            dataBindDgvInventory();
            dataBindCbFilterCategory();
        }

        // ucitavanje knjiga iz xml fajla
        private void btnImportBooks_Click(object sender, EventArgs e)
        {

            // pali formu

            // ideja je da se formi preda dr, te da forma otvori fajl i njegove sastojke spremi istovremeno
            // u dr i u bazu. i to je sve sto forma treba napravit - ovo sto slijedi azurira dr odnosno stvari
            // potrebne za prikaz podataka u glavnom programu

            // e sad, treba se dogovoriti koje sve podatke ce ti import fajlovi sadrzavati. sigurno ce sadrzavati
            // naziv knjige i autora te godinu izdavanja, te ce se vjerojatno cijena i kolicina u skladistu unositi
            // nakon ucitavanja iz fajla (po defaultu se mogu postaviti na 0 recimo). No treba dogovoriti jel 
            // ce se i kategorije importirati iz fajla, ili ce se i one naknadno unositi.


            // pocisti za sobom
            dr.makeCategoryList();
            dataBindDgvInventory();
            dataBindCbFilterCategory();
        }

        #endregion






















    }
}
